package com.card.game.room;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import com.card.common.CardContants;
import com.card.common.MessageComm;
import com.card.game.BasePlayer;
import com.card.game.Card;
import com.card.game.CardUtils;
import com.card.game.ZjhInfo;
import com.card.game.ZjhPlayer;
import com.card.game.BasePlayer.UserState;
import com.card.game.ddz.DdzPlayer;
import com.card.game.dn.NnPlayer;
import com.card.game.event.EventType;
import com.card.message.JsonMessageCenter;
import com.card.user.RoomBack;
import com.card.user.User;
import com.card.user.UserBack;
import com.card.user.UserUtils;
import com.google.common.collect.Lists;
import com.xiaoao.net.common.GameConstants;
import com.xiaoao.net.global.Global;
import com.xiaoao.net.json.message.JsonMessage;
import com.xiaoao.net.utils.StringUtil;

public class TggRoom extends AbstractRoom{
	public static final int Min_Player_Num = 2;
//	private static final int Max_Player_Num = 6;
	private static final int Max_Watch_Num = 0;
	
	protected transient Vector<BasePlayer> watchList = new Vector<>();
	private int curwhosTurn = -1;
	private transient long curhowsTurnStartTime;
//	protected transient int maxPlayerNum = Max_Player_Num;
	protected transient RoomBack roomBack;
	
	public transient RoomState lastState;
	public transient long lastStateTime;
	public boolean isCanStart;
	public transient ZjhRoomInfo zjhRoomInfo;
	
	public TggRoom(String ownerId,RoomSetting roomSetting) {
		super(CardContants.GAMETYPE_TGG,ownerId);
		setRoomSetting(roomSetting);
		this.roomBack = new RoomBack(this);
		this.zjhRoomInfo = new ZjhRoomInfo(this);
	}
	public TggRoom(ZjhPlayer player,RoomSetting roomSetting) {
		super(CardContants.GAMETYPE_TGG,player.getUserId());
		setRoomSetting(roomSetting);
		this.roomBack = new RoomBack(this);
		this.zjhRoomInfo = new ZjhRoomInfo(this);
		player.setTableIndex(0);
		super.addPlayer(player);
		//通知所有人房间信息改变
		sendRoomInfo();
	}
	
	@Override
	public void addPlayer(BasePlayer player) {
		synchronized (this.playerList) {
			if(this.playerList.size()<getMaxUserNum()) {
				player.setTableIndex(this.playerList.size());
				super.addPlayer(player);
				this.isCanStart = true;
				//通知所有人房间信息改变
				sendRoomInfo();
				return;
			}
		}
		synchronized (this.watchList) {
			if(this.watchList.size()<Max_Watch_Num) {
				JsonMessageCenter.getInstance().sendEorrorMessage(player.getUser(), "游戏已满员，您现在是观战模式！");
				player.setTableIndex(-1);
				this.watchList.add(player);
				player.getUser().setRoom(this);
				//通知所有人房间信息改变
				sendRoomInfoToPlayer(player);
			}
		}
	}
	
	@Override
	public boolean isFull() {
		return this.playerList.size()>=getMaxUserNum()
				&&this.watchList.size()>=Max_Watch_Num;
	}
	@Override
	public void broadcast(JsonMessage message) {
		super.broadcast(message);
		Iterator<BasePlayer> it = this.watchList.iterator();
		while (it.hasNext()) {
			BasePlayer player = it.next();
			JsonMessageCenter.getInstance().sendMessage(message, player);
		}
	}
	@Override
	public void startGame() {
		this.playNum++;
		super.startGame();
		setState(RoomState.Running);
		if(this.curwhosTurn<0) this.curwhosTurn = 0;
		this.zjhRoomInfo.curBet = roomSetting.getDiFen();
		this.zjhRoomInfo.lastIndex = this.playerList.size()-1;
		this.tableCards = CardUtils.createTGG();
		for (int i = 0; i < playerList.size(); i++) {
			ZjhPlayer player = (ZjhPlayer)playerList.get(i);
			Vector<Card> outCard = CardUtils.faPaiToVector(this.tableCards, 3);
			player.initCards(outCard);
			addBet(player, roomSetting.getDiFen());
			sendStarGameMessage(player);
		}
		broadChuPai();
		sendZjhInfo();
		Global.logErrorMessage("=================总牌数"+this.tableCards.size()+"==========");
	}
	
	public void broadChuPai() {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_ChuPai);
		message.addProperty("curwhosTurn", curwhosTurn);
		broadcast(message);
	}
	
	public int getNextPlayer() {
        return curwhosTurn == getMaxUserNum() - 1 ? 0 : curwhosTurn + 1;
    }
	public int getNextPlayerByIndex(int tableIndex) {
        return tableIndex == getMaxUserNum() - 1 ? 0 : tableIndex + 1;
    }
	
	public void sendStarGameMessage(BasePlayer player) {
		JsonMessage message = new JsonMessage(MessageComm.S2C_StartGame);
		message.addProperty("hand", CardUtils.AnPai);
		message.addProperty("curwhosTurn", curwhosTurn);
		JsonMessageCenter.getInstance().sendMessage(message, player);
	}
	
	public boolean isNoLunType(EventType type) {
		return type != EventType.KanPai && type != EventType.RengPai;
	}
	
	public void doSkill(String userId,EventType type,JsonMessage msg) {
		ZjhPlayer player = getPlayerById(userId);
		if(isNoLunType(type) && player.getTableIndex() != curwhosTurn) {
			Global.logErrorMessage("不该你操作！！！"+player.getTableIndex()+"  curwhosTurn:"+curwhosTurn);
			return;
		}
		if(isNoLunType(type) && player.zjhInfo.isOver()) {
			Global.logErrorMessage("你已经结束了"+player.getTableIndex()+"  curwhosTurn:"+curwhosTurn);
			return;
		}
		int menNum = getMenNum();
		if(this.zjhRoomInfo.curLun <= menNum
				&& type == EventType.BiPai
				&& type == EventType.KanPai) {
			return;
		}
		synchronized (this) {
			if(isNoLunType(type)) {
				addLun();
			}
			if(type == EventType.GenZhu) {
				genZhu(player);
			}else if(type == EventType.JiaZhu) {
				int value = msg.getAsInt("value");
				jiaZhu(player,value);
			}else if(type == EventType.KanPai) {
				kanPai(player);
			}else if(type == EventType.RengPai) {
				qiPai(player);
			}else if(type == EventType.BiPai) {
				int value = msg.getAsInt("value");
				if(biPai(player,value)) {
					return;
				}
			}
			if(isNoLunType(type)) {
				if(this.zjhRoomInfo.curLun == getMaxGen()) {
					ZjhPlayer winPlayer = getMaxPlayer();
					if(winPlayer != null) {
						calGameEnd(winPlayer);
					}
				}
			}
		}
	}
	
	public void broadSkill(EventType type,String userId,int value) {
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_ZjhSkill);
		message.addProperty("type", type.toString());
		message.addProperty("userId", userId);
		message.addProperty("value", value);
		broadcast(message);
	}
	
	
	@Override
	public void doTimedTask() {
		if(state == RoomState.BiPai) {
			long waitTime = System.currentTimeMillis() - this.stateChangeTime;
			if(waitTime > GameConstants.SECOND) {
				setState(RoomState.Running);
				if(!checkWin()) {
					if(this.zjhRoomInfo.curLun == getMaxGen()) {
						ZjhPlayer winPlayer = getMaxPlayer();
						if(winPlayer != null) {
							calGameEnd(winPlayer);
							return;
						}
					}
					sendZjhInfo();
					nextDoPlayer();
				}
			}
		}
		/**
		 * 	判断脱管状态
		 * 
		 * */ 
		else if(state == RoomState.Running) {
			if(getChangeStateTime() > 20*GameConstants.SECOND) {
				autoOutCard();
			}
		}

	}
	
	
	/**
	 *  
	 *  托管
	 * 
	 * */
	public void autoOutCard() {
		ZjhPlayer curPlayer = getPlayerByTableIndex(this.curwhosTurn);
		if(curPlayer != null) {
			qiPai(curPlayer);
		}
	}
//	public void setState(RoomState state) {
//		super.setState(state);
//		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_Room_State_Update);
//		message.addProperty("state", this.state.toString());
//		broadcast(message);
//	}
	@Override
	public void clearRoom() {
		super.clearRoom();
		this.zjhRoomInfo = null;
		this.watchList.clear();
		this.roomBack = null;
	}
	
	public void endGame() {
//		setState(RoomState.End);
		super.endGame();
		if(this.playNum  >= roomSetting.getMaxPlayNum()) {
			roomEnd();
			clearRoom();
			return;
		}
	}
	
	public void roomEnd() {
		sendRoomInfo();
		JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_ZjhAllOver);
		broadcast(message);
		this.roomBack.loadScore(this);
		for (BasePlayer basePlayer : playerList) {
			User user = UserUtils.getUserByPrimaryKey(basePlayer.getUserId());
			if(user != null) {
				user.userPlayBacks().addZjhRoomBack(roomBack);
				user.sendUserUpdateMessage();
			}
		}
	}
	
	@Override
	public void disbandRoom() {
		if(isStartGame) {
			roomEnd();
		}else{
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_RoomDisband);
			message.addProperty("firstId", ownerId);
			broadcast(message);
		}
		clearRoom();
	}
	@Override
	public void disbandAgencyRoom() {
		if(isStartGame) {
			roomEnd();
		}else{
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_RoomDisband);
			message.addProperty("firstId", ownerId);
			broadcast(message);
		}
		clearRoom();
	}
	@Override
	public void breakConnect(BasePlayer player) {
		JsonMessage message1 = new JsonMessage(MessageComm.C2S_BreakConnect);
		message1.addProperty("room", this);
		JsonMessageCenter.getInstance().sendMessage(message1, player);
		if(isStartGame) {
			((ZjhPlayer)player).sendHandMessage();
			sendZjhInfo();
			JsonMessage message = JsonMessage.createMessage(MessageComm.S2C_ChuPai);
			message.addProperty("curwhosTurn", curwhosTurn);
			JsonMessageCenter.getInstance().sendMessage(message, player);
		}
		player.changeOnline(true);
	} 
	public ZjhPlayer getPlayerById(String userId) {
		return (ZjhPlayer)super.getPlayerById(userId);
	}
	public ZjhPlayer getPlayerByTableIndex(int index) {
		return (ZjhPlayer)super.getPlayerByTableIndex(index);
	}
	public void changeWhoTurn(int nextTurn) {
		this.curwhosTurn = nextTurn;
		this.curhowsTurnStartTime = System.currentTimeMillis();
	}
	public void nextDoPlayer() {
		//通知其他人发牌
		ZjhPlayer nextPlayer = getNextZjhPlayer();
		changeWhoTurn(nextPlayer.getTableIndex());
		broadChuPai();
	}
	
	private ZjhPlayer getNextZjhPlayer() {
		int curIndex = curwhosTurn;
		for (int i = 0; i < getMaxUserNum(); i++) {
			int nextTurn = getNextPlayerByIndex(curIndex);
			ZjhPlayer nextPlayer = getPlayerByTableIndex(nextTurn);
			if(nextPlayer != null && !nextPlayer.zjhInfo.isOver() ) {
				return nextPlayer;
			}
			curIndex = nextTurn;
		}
		return null;
	}
	
	private ZjhPlayer getWinPlayer() {
		ZjhPlayer winPlayer = null;
		for (BasePlayer basePlayer : playerList) {
			ZjhPlayer p = (ZjhPlayer)basePlayer;
			if(!p.zjhInfo.isOver()) {
				if(winPlayer != null) {
					return null;
				}
				winPlayer = p;
			}
		}
		return winPlayer;
	}
	
	private boolean checkWin() {
		ZjhPlayer winPlayer = getWinPlayer();
		if(winPlayer == null) {
			return false;
		}
		calGameEnd(winPlayer);
		return true;
	}
	
	private void calGameEnd(ZjhPlayer winPlayer) {
		UserBack userBack = new UserBack(this);
		for (BasePlayer basePlayer : playerList) {
			ZjhPlayer player = (ZjhPlayer)basePlayer;
			int winScore = -player.zjhInfo.betNum;
			if(StringUtil.equals(player.getUserId(), winPlayer.getUserId())) {
				winScore += this.zjhRoomInfo.totalBet;
			}
			player.addScore(winScore);
			userBack.addScore(player.nickName, winScore);
			sendZjhEnd(player,winPlayer.getUserId());
		}
//		sendRoomInfo();
//		roomBack.addBackList(userBack);
		for (BasePlayer basePlayer : playerList) {
			ZjhPlayer player = (ZjhPlayer)basePlayer;
			player.clearData();
		}
		this.curwhosTurn = winPlayer.getTableIndex();
		this.zjhRoomInfo.clear();
		endGame();
	}
	
	private void sendZjhEnd(ZjhPlayer player,String winUserId) {
		JsonMessage message = new JsonMessage(MessageComm.S2C_ZjhEnd);
		message.addProperty("myhand", player.getEndMyCard());
		message.addProperty("winUserId", winUserId);
		for (BasePlayer basePlayer : playerList) {
			ZjhPlayer tempPlayer = (ZjhPlayer)basePlayer;
			if(!StringUtil.equals(player.getUserId(), tempPlayer.getUserId())) {
				message.addProperty("hand"+tempPlayer.getTableIndex(), tempPlayer.getEndCard());
			}else{
				message.addProperty("hand"+tempPlayer.getTableIndex(), player.getEndMyCard());
			}
		}
		JsonMessageCenter.getInstance().sendMessage(message, player);
	}
	
	private void kanPai(ZjhPlayer player) {
		if(player == null || player.zjhInfo.isKanPai) {
			return;
		}
		broadSkill(EventType.KanPai, player.getUserId(), 0);
		player.zjhInfo.isKanPai = true;
		player.sendHandMessage();
		sendZjhInfo();
	}
	
	private void qiPai(ZjhPlayer player) {
		player.zjhInfo.qiPai();
		broadSkill(EventType.RengPai, player.getUserId(), 0);
		changeLastIndex();
		sendZjhInfo();
		if(!checkWin()) {
			if(player.getTableIndex() == curwhosTurn) {
				nextDoPlayer();
			}
		}
	}
	
	private void genZhu(ZjhPlayer player) {
		int value = this.zjhRoomInfo.curBet;
		if(!player.zjhInfo.isKanPai && this.zjhRoomInfo.curBet > roomSetting.getDiFen()) {
			int temp = value/2;
			value = value%2==1?temp+1:temp;
		}
		value = Math.max(1, value);
		broadSkill(EventType.GenZhu, player.getUserId(), value);
		addBet(player, value);
		setBet(player, value);
		sendZjhInfo();
		nextDoPlayer();
	}
	
	private void jiaZhu(ZjhPlayer player,int value) {
		addBet(player, value);
		setBet(player, value);
		broadSkill(EventType.JiaZhu, player.getUserId(), value);
		sendZjhInfo();
		nextDoPlayer();
	}
	
	private boolean biPai(ZjhPlayer player,int oppIndex) {
		ZjhPlayer tempPlayer = getPlayerByTableIndex(oppIndex);
		System.out.println(tempPlayer+"-----比牌------");
		if(tempPlayer.zjhInfo.isOver() || player.zjhInfo.isOver()) {
			return true;
		}
		int value = this.zjhRoomInfo.curBet;
		if(player.zjhInfo.isKanPai) {
			value = Math.min(value*2, roomSetting.getBetLimit());
		}
		addBet(player, value);
		broadSkill(EventType.BiPai, player.getUserId(), value);
		sendZjhInfo();
		String oppId = tempPlayer.getUserId();
		boolean isWin = player.compare(tempPlayer)>0;
		if(isWin) {
			tempPlayer.zjhInfo.lost();
		}else{
			player.zjhInfo.lost();
		}
		changeLastIndex();
		
		player.zjhInfo.addBiPaiUser(tempPlayer);
		tempPlayer.zjhInfo.addBiPaiUser(player);
		JsonMessage message = new JsonMessage(MessageComm.S2C_BiPai);
		message.addProperty("userId", player.getUserId());
		message.addProperty("oppoUserId", oppId);
		message.addProperty("winUser", isWin?player.getUserId():oppId);
		broadcast(message);
		
//		ZjhPlayer winPlayer = getWinPlayer();
//		if(winPlayer != null) {
//			for (BasePlayer p : playerList) {
//				ZjhPlayer jhp = (ZjhPlayer)p;
//				if(!StringUtil.equals(jhp.getUserId(), player.getUserId())
//						&&!StringUtil.equals(jhp.getUserId(), tempPlayer.getUserId())) {
//					jhp.zjhInfo.addBiPaiUser(player);
//					jhp.zjhInfo.addBiPaiUser(tempPlayer);
//				}
//			}
//		}
//		setState(RoomState.BiPai);
		if(!checkWin()) {
			sendZjhInfo();
			nextDoPlayer();
			return false;
		}
		return true;
	}
	
	private void addBet(ZjhPlayer player,int value) {
		addRoomBet(value);
		player.zjhInfo.betNum += value;
	}
	
	private void addRoomBet(int value) {
		this.zjhRoomInfo.totalBet += value;
		this.zjhRoomInfo.chipList.add(value);
	}
	
	private List<ZjhInfo> getZjhInfos() {
		List<ZjhInfo> list = Lists.newArrayList();
		for (BasePlayer p : playerList) {
			list.add(((ZjhPlayer)p).zjhInfo);
		}
		return list;
	}
	
	public void sendZjhInfo() {
		JsonMessage message = new JsonMessage(MessageComm.S2C_RoomZjhInfo);
		message.addProperty("roomZjhInfo", this.zjhRoomInfo);
		message.addProperty("userZjhInfoList", getZjhInfos());
		message.addProperty("curwhosTurn", curwhosTurn);
		broadcast(message);
	}
	
	private void setBet(ZjhPlayer player,int value) {
		if(!player.zjhInfo.isKanPai) {
			value *= 2;
		}
		this.zjhRoomInfo.curBet = value;
	}
	
	private void addLun() {
		if(this.curwhosTurn == this.zjhRoomInfo.lastIndex) {
			this.zjhRoomInfo.curLun++;
		}
	}
	private void changeLastIndex() {
		this.zjhRoomInfo.lastIndex = getLastIndex();
	}
	private int getLastIndex() {
		int size = this.playerList.size();
		for (int i = size-1; i >= 1; i--) {
			ZjhPlayer p = getPlayerByTableIndex(i);
			if(!p.zjhInfo.isOver()) {
				return i;
			}
		}
		return 1;
	}
	
	public ZjhPlayer getMaxPlayer() {
		ZjhPlayer winPlayer = null;
		List<Integer> tempIndex = Lists.newArrayList();
		for (BasePlayer p : playerList) {
			ZjhPlayer jhp = (ZjhPlayer)p;
			if(!jhp.zjhInfo.isOver()) {
				tempIndex.add(jhp.getTableIndex());
				if(winPlayer == null || jhp.compare(winPlayer) > 0) {
					winPlayer = jhp;
				}
			}
		}
		for (BasePlayer p : playerList) {
			ZjhPlayer jhp = (ZjhPlayer)p;
			jhp.zjhInfo.addBiPaiUser(tempIndex);
		}
		return winPlayer;
	}
	@Override
	public int getMaxUserNum() {
//		return this.playerList.size();
		return roomSetting.getUserNum();
	}
	
	public int getMenNum() {
		return roomSetting.getMenNum();
	}
	
	public int getMaxGen() {
		return roomSetting.getMaxLunNum();
	}
}
